package com.music.note_android.ui.editor

import android.graphics.RectF

/**
 * 笔画数据模型
 * 存储单次绘制操作的所有信息，包括工具类型、颜色、粗细、路径点等
 */
data class Stroke(
    /**
     * 笔画的唯一标识符
     */
    val id: String,
    
    /**
     * 使用的绘制工具
     */
    val tool: DrawingTool,
    
    /**
     * 笔画颜色（ARGB格式）
     */
    val color: Int,
    
    /**
     * 基础笔画粗细
     */
    val width: Float,
    
    /**
     * 笔画路径上的所有点
     */
    val points: List<StrokePoint>,
    
    /**
     * 笔画创建时间戳
     */
    val timestamp: Long,
    
    /**
     * 笔画透明度（0.0-1.0）
     */
    val alpha: Float = 1.0f
) {
    
    /**
     * 计算笔画的边界矩形
     * 用于优化渲染和碰撞检测
     */
    fun getBounds(): RectF {
        if (points.isEmpty()) {
            return RectF(0f, 0f, 0f, 0f)
        }
        
        var minX = Float.MAX_VALUE
        var minY = Float.MAX_VALUE
        var maxX = Float.MIN_VALUE
        var maxY = Float.MIN_VALUE
        
        // 考虑笔画粗细的影响
        val maxWidth = getMaxWidth()
        val halfWidth = maxWidth / 2f
        
        points.forEach { point ->
            minX = minOf(minX, point.x - halfWidth)
            minY = minOf(minY, point.y - halfWidth)
            maxX = maxOf(maxX, point.x + halfWidth)
            maxY = maxOf(maxY, point.y + halfWidth)
        }
        
        return RectF(minX, minY, maxX, maxY)
    }
    
    /**
     * 获取笔画中的最大粗细
     * 考虑压感对粗细的影响
     */
    fun getMaxWidth(): Float {
        if (!tool.supportsPressure()) {
            return width
        }
        
        val maxPressure = points.maxOfOrNull { it.pressure } ?: 1.0f
        return width * (0.5f + maxPressure * 1.5f) // 压感范围：50%-200%
    }
    
    /**
     * 获取笔画中的最小粗细
     */
    fun getMinWidth(): Float {
        if (!tool.supportsPressure()) {
            return width
        }
        
        val minPressure = points.minOfOrNull { it.pressure } ?: 1.0f
        return width * (0.5f + minPressure * 1.5f)
    }
    
    /**
     * 获取笔画的总长度
     */
    fun getLength(): Float {
        if (points.size < 2) {
            return 0f
        }
        
        var totalLength = 0f
        for (i in 1 until points.size) {
            val prev = points[i - 1]
            val curr = points[i]
            val dx = curr.x - prev.x
            val dy = curr.y - prev.y
            totalLength += kotlin.math.sqrt(dx * dx + dy * dy)
        }
        
        return totalLength
    }
    
    /**
     * 检查指定点是否在笔画范围内
     * 用于橡皮擦的碰撞检测
     */
    fun containsPoint(x: Float, y: Float, tolerance: Float = 5f): Boolean {
        val bounds = getBounds()
        
        // 首先检查是否在边界矩形内
        if (!bounds.contains(x, y)) {
            return false
        }
        
        // 检查是否在笔画路径附近
        for (i in 1 until points.size) {
            val prev = points[i - 1]
            val curr = points[i]
            
            val distance = distanceToLineSegment(x, y, prev.x, prev.y, curr.x, curr.y)
            val strokeWidth = if (tool.supportsPressure()) {
                width * (0.5f + ((prev.pressure + curr.pressure) / 2f) * 1.5f)
            } else {
                width
            }
            
            if (distance <= strokeWidth / 2f + tolerance) {
                return true
            }
        }
        
        return false
    }
    
    /**
     * 计算点到线段的距离
     */
    private fun distanceToLineSegment(
        px: Float, py: Float,
        x1: Float, y1: Float,
        x2: Float, y2: Float
    ): Float {
        val dx = x2 - x1
        val dy = y2 - y1
        
        if (dx == 0f && dy == 0f) {
            // 线段退化为点
            val dpx = px - x1
            val dpy = py - y1
            return kotlin.math.sqrt(dpx * dpx + dpy * dpy)
        }
        
        val t = ((px - x1) * dx + (py - y1) * dy) / (dx * dx + dy * dy)
        
        val closestX: Float
        val closestY: Float
        
        when {
            t < 0 -> {
                closestX = x1
                closestY = y1
            }
            t > 1 -> {
                closestX = x2
                closestY = y2
            }
            else -> {
                closestX = x1 + t * dx
                closestY = y1 + t * dy
            }
        }
        
        val dpx = px - closestX
        val dpy = py - closestY
        return kotlin.math.sqrt(dpx * dpx + dpy * dpy)
    }
    
    /**
     * 创建笔画的副本，用于撤销重做功能
     */
    fun copy(): Stroke {
        return Stroke(
            id = id,
            tool = tool,
            color = color,
            width = width,
            points = points.toList(), // 创建点列表的副本
            timestamp = timestamp,
            alpha = alpha
        )
    }
    
    /**
     * 判断笔画是否为空（没有有效的绘制内容）
     */
    fun isEmpty(): Boolean {
        return points.isEmpty() || (points.size == 1 && getLength() == 0f)
    }
    
    /**
     * 获取笔画的简要描述，用于调试
     */
    override fun toString(): String {
        return "Stroke(id=$id, tool=$tool, color=#${Integer.toHexString(color)}, " +
                "width=$width, points=${points.size}, length=${String.format("%.2f", getLength())})"
    }
}